/*
 *
 *  This file is part of Cfu
 *
 *  Cfu is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  
 *  Cfu is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with Cfu. If not, see <http://www.gnu.org/licenses/>.
 *
 *  json.cc - william le ferrand (william@corefarm.com) 29/04/2010 15:30
 *
 */

// STL
#include <iostream>
#include <ostream> 
#include <string> 
#include <algorithm> 
#include <iterator> 
#include <cstring> 

// JSON
#include <tinyjson.hpp>

// BOOST
#include <boost/test/auto_unit_test.hpp> 
#include <boost/test/floating_point_comparison.hpp> 
#include <boost/lambda/lambda.hpp> 
#include <boost/lambda/casts.hpp> 

// CFU
#include <errors.hpp>

std::string to_utf8(const std::wstring &ws) 
{ 
	char buffer[1024]; 
	std::size_t size = std::wcstombs(buffer, ws.c_str(), sizeof(buffer)); 
	return std::string(buffer, size); 
} 

namespace std 
{ 
	std::ostream &operator<<(std::ostream &os, const std::type_info &ti) 
	{ 
		return os << ti.name(); 
	} 

	std::ostream &operator<<(std::ostream &os, const std::wstring &ws) 
	{ 
		return os << to_utf8(ws); 
	} 

	std::ostream &operator<<(std::ostream &os, const std::basic_string<int> &is) 
	{ 
		std::wstring ws; 
		std::transform(is.begin(), is.end(), std::back_inserter(ws), boost::lambda::ll_static_cast<wchar_t>(boost::lambda::_1)); 
		return os << to_utf8(ws); 
	} 
} 

template <typename T> T strip(std::string &json, const char *target)
{
  
  json::grammar<wchar_t>::variant var = json::parse(json.begin(), json.end());
  
  if(var->type() != typeid(json::grammar<char>::object))
    {
      // ERROR: parsing failed (bad format)
      throw (new json_error ()); 
    }
  
  json::grammar<char>::object obj = boost::any_cast<json::grammar<char>::object>(*var);
  
  json::grammar<char>::object::iterator it = obj.begin(); 
  
      for(json::grammar<char>::object::const_iterator it = obj.begin(); it != obj.end(); ++it)
	{
	  std::string field = boost::any_cast<std::string>((*it).first);
	  
	  if (!(field.compare (target))) 
	    {
	      return (boost::any_cast<T>(*it->second)); 
	    } ;      
	}
      
      throw (new missing_field ()); 
      
}


// I'm bad at template programing. 

int strip_int (std::string &j, const char *f) 
{
  return (strip <int> (j, f)); 
}


std::string strip_string (std::string &j, const char *f)
{
  return (strip <std::string> (j, f)); 
}

std::wstring strip_wstring (std::string &j, const char *f)
{
  return (strip <std::wstring> (j, f)); 
}
